'''
=== ASSUMPTIONS ===

    1) Rigs will be built for Dota2 assets
        a) In the case of champions there is no need to build
            a skeleton
    
=== WORKFLOW ===

    1) Create the modules needed for the rig
    2) For each module
        a) Position the joint/ctrl markers
        b) Pick which control shapes to use for each module part
        c) Set control names
        b) Connect modules
            i) Module connection window
    3) Build the modules
        a) Build the rigging (optional)
        b) Build the skeleton (optional)
    4) Build the hierarchies
        a) Rigging
        b) Skeleton
    5) Build the constraints
        a) Constrain the skeleton to the rigging
        
=== MODULE ===

    Properties
        1) Name
        2) Side (Left/Right) ComboBox
        
    1) Made up of markers
        a) Each marker represents a control, joint or both
        b) Polygon
            i) Sphere - joint
            ii) 
        c) Spans
            i) Represent the direction of the joint
            ii) Colored to match the axis it points down
    2) 
    
=== MARKERS ===

    Properties
        1) Name
            a) Starts with a temp name
        2) Parent Proxy
            a) If this marker is assigned as a parent to another
                module, then the Parent Proxy is used instead. This
                is so the user doesn't need to know about parenting
                to a spacer or some other hidden rigging object.
        3) Control Type
            a) Stores the control type chosen by the user.
            
=== UIs ===

    Connection Window
        1) Like the connection editor in Maya
        2) Two columns - left is child, right is parent
        3) Column lists viable items to be a child or parent (depending
            on which column it is)
        4) Click the child, click the parent and then click 'OK'
    
    Module Inspector
        1) Lists all the parts of a module
        2) Each part is a collapsible section
            a) Lists the properties
            b) This is where they are edited directly or by opening some
                sub-editor unique to a property
                
    Marker Matcher
        1) Transforms a marker to match a target object. Used primarily for
            characters that already have skeletons.
        2) Select the marker then select the target joint.
        3) Moves the markers spacer NOT THE MARKER.
'''

'''
============================================================
--->>   IMPORT MODULES
============================================================
'''
import masdevallia.settings.PathConstants as PathConstants
import masdevallia.utility.WindowUtility as WinUtility
from PySide import QtCore
from PySide import QtGui


import maya.cmds as CMDS

import math, sys, types

import maya.OpenMaya as OpenMaya

import masdevallia.utility.Dag as Dag
import masdevallia.utility.Matrix as Matrix
import masdevallia.nodes.Node as Node
import masdevallia.utility.Selection as Selection
import masdevallia.utility.General as General

        
'''
============================================================
--->>   GLOBAL VARIABLES
============================================================
'''
form_class, base_class = WinUtility.loadUiType( PathConstants.WINDOW_DOTA_RIGGER_GUI )
edit_parts_form_class, edit_parts_base_class = WinUtility.loadUiType( PathConstants.WINDOW_DOTA_EDIT_PARTS_GUI )
marker_tile_form_class, marker_tile_base_class = WinUtility.loadUiType( PathConstants.WIDGET_DOTA_MARKER_TILE_GUI )


'''
============================================================
--->>   RIG TOOLS CLASS
============================================================
'''
class DotaRiggerWindow( form_class, base_class ):
    def __init__( self, parent=None ):
        super( DotaRiggerWindow, self).__init__( parent )
        self.setupUi( self )
        self.setWindowFlags( QtCore.Qt.Window )
        self.setObjectName( 'Dota_Rigger_Window' )
        
        self.dock = None
        '''Name of the docked window.'''
        
        self.previousMode = None
        self.currentMode = 'modules'
        '''Tracks the current mode of the window.'''
        
        self.initUi()
        self.initConnections()
        
    def initUi( self ):
        '''
        Initial UI setup.
        '''
        self.central_layout.setAlignment( QtCore.Qt.AlignTop )
        
    def initConnections( self ):
        '''
        Initial GUI connections.
        '''
        self.modules_bin.clicked.connect( self.openModulesBin )
        self.edit_parts.clicked.connect( self.openEditParts )
        self.module_linker.clicked.connect( self.openModuleLinker )
        self.build_rig.clicked.connect( self.buildRig )
        
    def openModulesBin( self ):
        '''
        Opens modules bin tool.
        '''
        print 'OPEN MODULES BIN'
        
    def openEditParts( self ):
        '''
        Opens the edit parts tool.
        '''
        editor = DotaEditPartsWindow( parent=WinUtility.mayaMainWindow() )
        editor.show()
        
    def openModuleLinker( self ):
        '''
        Opens the module linker tool.
        '''
        print 'OPEN MODULE LINKER'
        
    def buildRig( self ):
        '''
        Builds the entire rig.
        '''
        print 'BUILD RIG'
        
        
class DotaEditPartsWindow( edit_parts_base_class, edit_parts_form_class ):
    def __init__( self, parent=None ):
        super( DotaEditPartsWindow, self).__init__( parent )
        self.setupUi( self )
        self.setWindowFlags( QtCore.Qt.Window )
        self.setObjectName( 'Dota_Edit_Parts_Window' )
        
        # Stores the currently selected module as a Node.
        self.current_module = None
        self.current_meta_node = None
        
        self.initConnections()
        
    def initConnections( self ):
        '''
        Initial GUI connections.
        '''
        self.module_refresh.clicked.connect( self.refreshModule )
        
    def refreshModule( self ):
        '''
        Refreshes the selected module.
        '''
        sel_list = OpenMaya.MSelectionList()
        OpenMaya.MGlobal.getActiveSelectionList( sel_list )
        
        if sel_list.length() == 1:
            obj = OpenMaya.MObject()
            sel_list.getDependNode( 0, obj )
            meta_plug = Dag.getPlugByName( obj, 'metaNode' )
            
            if meta_plug is not None:
                meta_connections = Dag.getPlugConnections( meta_plug, False, True )
                
                if meta_connections is not None:
                    # Get an instance of the module meta node.
                    meta_node_name = meta_connections[0].name().split( '.' )[0]
                    self.current_meta_node = General.getMetaNode( meta_node_name )
                
                    # Get the module and update the label.
                    module_root_plug = Dag.getPlugByName( obj, 'moduleRoot' )                    
                    module_root_name = Dag.getPlugValue( module_root_plug )
                    module_root_obj = Dag.getMObject( module_root_name )
                    module_root_plug = Dag.getPlugByName( module_root_obj, 'moduleClass' )
                    module_class_name = Dag.getPlugValue( module_root_plug )
                    self.module_label.setText( module_class_name )
            

                
        
        '''
        if sel_list.length() == 1:
            obj = OpenMaya.MObject()
            sel_list.getDependNode( 0, obj )
            plug = Dag.getPlugByName( obj, 'moduleRoot')
            
            if plug is not None:
                sel_list = OpenMaya.MSelectionList()
                value = Dag.getPlugValue( plug )
                sel_list.add( value )
                root_obj = OpenMaya.MObject()
                sel_list.getDependNode( 0, root_obj )
                self.current_module = Node.Node( root_obj )
                self.module_label.setText( self.current_module.name )
                self.updatePartsWidgets()
        '''
             
    def updatePartsWidgets( self ):
        '''
        Refreshes the modules parts (markers, etc.) editor guis.
        '''
        # THIS STUFF NEEDS REPLACED WITH THE META NODES!!!!!!
        children = Dag.getChildren( self.current_module.asMObject(), inType=OpenMaya.MFn.kTransform )
        print children
        for child in children:
            node = Node.Node( str(child) )
            print node.name
            print '    {0}'.format( node.asMObject().apiTypeStr() )


class DotaMarkerTileWidget( marker_tile_base_class, marker_tile_form_class ):
    def __init__( self, parent=None ):
        super( DotaMarkerTileWidget, self).__init__( parent )
        self.setupUi( self )
        self.setWindowFlags( QtCore.Qt.Widget )
        self.setObjectName( 'Dota_Marker_Tile_Widget' )
        
        
        
############
#    THINGS TO MOVE
############

    
def getModuleNode( module_name, module_class ):
    '''
    Returns an instance of the module node.
    
    @param name: String. Name of the module.
    @return: Instance of the node.
    '''
    to_class = General.str_to_class( module_class )
    return to_class( node_name=module_name )
        
    
    
    
# WIDGETS
    


'''
===


===
'''
#import masdevallia.utility.WindowLauncher as WinLauncher
#WinLauncher.showWindow( 'RigTools' )



'''
# Main rigging window.
window = DotaRiggerWindow( parent=WinUtility.mayaMainWindow() )
dockName = PathConstants.WINDOW_RIG_TOOLS_DOCK
window.show()
'''

'''
# Show the window in dock mode.
if CMDS.dockControl( dockName, query=True, exists=True ):
    window.dock = CMDS.dockControl( dockName, vis=True, r=True, e=True )
else:
    window.dock = CMDS.dockControl( dockName, width=window.width(), vis=True, r=True, area='left', content=str(window.objectName()), label=str(window.windowTitle()) )
print window.dock
'''

'''
mtx = Matrix.Matrix( 'ct_wrist_L', 'worldMatrix' )
print mtx.getMatrixAsList()
rig_meta = RigMeta( node_name='RigMeta' )
'''











